package cn.cool.logic;

import cn.cool.basic.CdDropDownOperate;
import cn.cool.basic.CdResource;
import cn.cool.common.CdDropdownItem;
import cn.cool.common.CdDropdownValue;
import cn.cool.common.CdResult;
import cn.cool.config.CdConfigSetting;
import cn.cool.config.CdDefaultSetting;
import cn.cool.util.CdConstant;
import cn.cool.util.CdUtil;

import java.util.*;

public class CdLogicImpl implements CdLogicInterface {

    /**
     * 初始化数据
     */
    @Override
    public void initSettingData() {
        CdDropDownOperate.initSettingData();
    }

    /**
     * 初始化指定文件的数据
     *
     * @param configSet 配置信息文件名称
     */
    @Override
    public void initSettingData(CdConfigSetting configSet) {
        CdDropDownOperate.initSettingData(configSet);
    }

    /**
     * 获取所有数据
     *
     * @return 返回结果
     */
    @Override
    public CdResult getAllData() {
        return CdResult.success(getAllItemData(CdDropDownOperate.getAllConstData()));
    }

    @SuppressWarnings("unchecked")
    private List<CdDropdownValue> getAllItemData(Map<String, Object> allConstData) {
        List<CdDropdownValue> items = new ArrayList<>();
        for (Map.Entry<String, Object> nameSpaceEntry : allConstData.entrySet()) {
            String nameSpaceKey = nameSpaceEntry.getKey();
            Map<String, Object> nameSpaceMap = (Map<String, Object>) nameSpaceEntry.getValue();
            if (null != nameSpaceMap) {
                nameSpaceMap.keySet().forEach(typeKey -> {
                            Map<String, Object> typeMap = getDataMap(typeKey, nameSpaceMap);
                            if (!typeMap.isEmpty()) {

                                typeMap.keySet().forEach(dataKey -> {
                                    Map<String, Object> dataMap = getDataMap(dataKey, typeMap);
                                    if (!dataMap.isEmpty()) {
                                        CdDropdownValue item = new CdDropdownValue();
                                        item.setKey(nameSpaceKey + CdResource.CONST_SYMBOL_DOT + typeKey + CdResource.CONST_SYMBOL_DOT + dataKey);
                                        item.setValue(dataMap.get(CdDropDownOperate.CONST_VAL_DATA_KEY));
                                        item.setComment(dataMap.get(CdDropDownOperate.CONST_VAL_COMMENT_KEY).toString());
                                        item.setSequence((int) dataMap.get(CdDropDownOperate.CONST_VAL_ORIGINAL_SEQ_KEY));
                                        items.add(item);
                                    }
                                });
                            }
                        }
                );
            }
        }

        items.sort(Comparator.comparingInt(CdDropdownValue::getSequence));
        return items;
    }

    @SuppressWarnings("unchecked")
    private Map<String, Object> getDataMap(String key, Map<String, Object> dataMap) {
        if (dataMap.containsKey(key)) {
            return (Map<String, Object>) dataMap.get(key);
        }
        return Collections.emptyMap();
    }

    /**
     * 获取所有命名空间数据
     *
     * @return 返回结果
     */
    @Override
    public CdResult getAllNameSpaceData() {
        return CdResult.success(new ArrayList<>(CdDropDownOperate.getAllConstData().keySet()));
    }

    /**
     * 获取所有类型数据
     *
     * @param nameSpace 命名空间
     * @return 返回结果
     */
    @Override
    @SuppressWarnings("unchecked")
    public CdResult getAllTypeData(String nameSpace) {
        List<String> types = new ArrayList<>();
        Map<String, Object> allConstData = CdDropDownOperate.getAllConstData();
        if (allConstData.containsKey(nameSpace)) {
            Map<String, Object> nameSpaceMap = (Map<String, Object>) allConstData.get(nameSpace);
            if (!nameSpaceMap.isEmpty()) {
                types.addAll(nameSpaceMap.keySet());
            }
        }
        return CdResult.success(types);
    }

    /**
     * 获取命名空间类型下所有值数据
     *
     * @param nameSpace 命名空间
     * @param type      类型
     * @return 返回结果
     */
    @Override
    public CdResult getAllTypeKeyData(String nameSpace, String type) {
        List<CdDropdownItem> values = new ArrayList<>();

        Map<String, Object> nameSpaceMap = getDataMap(nameSpace, CdDropDownOperate.getAllConstData());
        if (nameSpaceMap.isEmpty()) return CdResult.success(values);

        Map<String, Object> typeMap = getDataMap(type, nameSpaceMap);
        getNameSpaceAndTypeMapData(nameSpace + CdConstant.CONST_SYMBOL_POINT + type, typeMap, values);
        return CdResult.success(values);
    }

    private void getNameSpaceAndTypeMapData(String keyPath, Map<String, Object> typeMap, List<CdDropdownItem> items) {
        List<CdDropdownValue> valueList = getCdDropdownValueData(keyPath, false, typeMap);
        convertItemList(valueList, items);
    }

    @SuppressWarnings("unchecked")
    private List<CdDropdownValue> getCdDropdownValueData(String keyPath, boolean isAddTopEmptyItem, Map<String, Object> typeMap) {
        List<CdDropdownValue> values = new ArrayList<>();
        if (typeMap.isEmpty()) return values;

        boolean isAdd = false;
        for (Map.Entry<String, Object> entry : typeMap.entrySet()) {
            Map<String, Object> valueMap = (Map<String, Object>) entry.getValue();

            if (isAddTopEmptyItem && !isAdd) {
                CdDropdownValue valueItem = new CdDropdownValue();
                valueItem.setKey(CdDefaultSetting.DROPDOWN_TOP_EMPTY_KEY);
                valueItem.setValue(CdDefaultSetting.DROPDOWN_TOP_EMPTY_VALUE);
                valueItem.setComment(CdDefaultSetting.DROPDOWN_TOP_EMPTY_COMMENT);
                valueItem.setSequence(Integer.MIN_VALUE);
                values.add(valueItem);
                isAdd = true;
            }

            CdDropdownValue valueItem = new CdDropdownValue();
            valueItem.setKey(CdUtil.isStrEmpty(keyPath) ? entry.getKey() : keyPath + CdConstant.CONST_SYMBOL_POINT + entry.getKey());
            valueItem.setValue(valueMap.get(CdDropDownOperate.CONST_VAL_DATA_KEY));
            valueItem.setComment((String) valueMap.get(CdDropDownOperate.CONST_VAL_COMMENT_KEY));
            valueItem.setSequence((int) valueMap.get(CdDropDownOperate.CONST_VAL_ORIGINAL_SEQ_KEY));
            values.add(valueItem);
        }

        values.sort(Comparator.comparingInt(CdDropdownValue::getSequence));

        return values;
    }

    private void convertItemList(List<CdDropdownValue> values, List<CdDropdownItem> items) {
        if (!values.isEmpty()) {
            values.forEach(value -> {
                        CdDropdownItem item = new CdDropdownItem();
                        item.setKey(value.getKey());
                        item.setValue(value.getValue());
                        item.setComment(value.getComment());
                        items.add(item);
                    }
            );
        }
    }

    /**
     * 获取命名空间类型下具体key键的数据值
     *
     * @param nameSpace 命名空间
     * @param type      类型
     * @param key       键
     * @return 返回结果
     */
    @Override
    public CdResult getKeyValueData(String nameSpace, String type, String key) {
        CdDropdownItem item = new CdDropdownItem();
        Map<String, Object> nameSpaceMap = getDataMap(nameSpace, CdDropDownOperate.getAllConstData());
        if (nameSpaceMap.isEmpty()) return CdResult.fail(CdConstant.GL_FAIL_NO_DATA_MSG);

        Map<String, Object> typeMap = getDataMap(type, nameSpaceMap);
        if (typeMap.isEmpty()) return CdResult.fail(CdConstant.GL_FAIL_NO_DATA_MSG);

        Map<String, Object> keyMap = getDataMap(key, typeMap);
        if (keyMap.isEmpty()) return CdResult.fail(CdConstant.GL_FAIL_NO_DATA_MSG);

        getKeyMapData(nameSpace + CdConstant.CONST_SYMBOL_POINT + type + CdConstant.CONST_SYMBOL_POINT + key, keyMap, item);
        return CdResult.success(item);
    }

    private void getKeyMapData(String key, Map<String, Object> keyMap, CdDropdownItem item) {
        item.setKey(key);
        item.setValue(keyMap.get(CdDropDownOperate.CONST_VAL_DATA_KEY));
        item.setComment((String) keyMap.get(CdDropDownOperate.CONST_VAL_COMMENT_KEY));
    }

    /**
     * 获取命名空间类型的下拉项数据 (获取命名空间类型下具体key键的数据值)
     *
     * @param nameSpace 命名空间
     * @param type      类型
     * @return 返回结果
     */
    @Override
    public List<CdDropdownItem> getDropDownListData(String nameSpace, String type) {
        List<CdDropdownItem> items = new ArrayList<>();
        if (CdUtil.isStrEmpty(nameSpace) || CdUtil.isStrEmpty(type)) return items;

        Map<String, Object> nameSpaceMap = getDataMap(nameSpace, CdDropDownOperate.getAllConstData());
        if (nameSpaceMap.isEmpty()) return items;

        Map<String, Object> typeMap = getDataMap(type, nameSpaceMap);
        if (typeMap.isEmpty()) return items;

        List<CdDropdownValue> valueList = getCdDropdownValueData(null, false, typeMap);
        convertItemList(valueList, items);

        return items;
    }

    /**
     * 获取命名空间类型包含首项的下拉项数据 (获取命名空间类型下具体key键的数据值)
     *
     * @param nameSpace 命名空间
     * @param type      类型
     * @return 返回结果
     */
    @Override
    public List<CdDropdownItem> getDropDownListTopEmptyData(String nameSpace, String type) {
        List<CdDropdownItem> items = new ArrayList<>();
        if (CdUtil.isStrEmpty(nameSpace) || CdUtil.isStrEmpty(type)) return items;

        Map<String, Object> nameSpaceMap = getDataMap(nameSpace, CdDropDownOperate.getAllConstData());
        if (nameSpaceMap.isEmpty()) return items;

        Map<String, Object> typeMap = getDataMap(type, nameSpaceMap);
        if (typeMap.isEmpty()) return items;

        List<CdDropdownValue> valueList = getCdDropdownValueData(null, true, typeMap);
        convertItemList(valueList, items);

        return items;
    }

    /**
     * 获取命名空间数据个数
     *
     * @return 返回结果
     */
    @Override
    public int getNameSpaceCount() {
        return CdDropDownOperate.getAllConstData().keySet().size();
    }

    /**
     * 获取命名空间下类型个数
     *
     * @param nameSpace 命名空间
     * @return 返回结果
     */
    @Override
    @SuppressWarnings("unchecked")
    public int getTypeCount(String nameSpace) {
        Map<String, Object> allConstData = CdDropDownOperate.getAllConstData();
        if (allConstData.containsKey(nameSpace)) {
            Map<String, Object> nameSpaceMap = (Map<String, Object>) allConstData.get(nameSpace);
            return nameSpaceMap.keySet().size();
        }
        return 0;
    }

    /**
     * 获取命名空间下类型的key个数
     *
     * @param nameSpace 命名空间
     * @param type      类型
     * @return 返回结果
     */
    @Override
    public int getTypeKeyCount(String nameSpace, String type) {
        Map<String, Object> nameSpaceMap = getDataMap(nameSpace, CdDropDownOperate.getAllConstData());
        if (nameSpaceMap.isEmpty()) return 0;

        Map<String, Object> typeMap = getDataMap(type, nameSpaceMap);
        if (typeMap.isEmpty()) return 0;

        return typeMap.keySet().size();
    }

}
